using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using System.Reactive.Linq;
using ReactiveChannelMessaging.Core;
using ReactiveChannelMessaging.Services;
using ReactiveChannelMessaging.Examples;
using ReactiveChannelMessaging.WinForms;

namespace ReactiveChannelMessaging;

/// <summary>
/// 主程序入口 - 支持控制台和WinForms模式
/// </summary>
class Program
{
    [STAThread]
    static void  Main(string[] args)
    {
        // 检查是否有命令行参数指定控制台模式
        
     
            RunWinFormsMode();
    }

    static void RunWinFormsMode()
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        
        try
        {
            SimpleMainForm form = new SimpleMainForm();
            Application.Run(form);
        }
        catch (Exception ex)
        {
            MessageBox.Show($"应用程序启动失败:\n{ex.Message}", "错误", 
                MessageBoxButtons.OK, MessageBoxIcon.Error);
        }
    }

    static async Task RunConsoleMode(string[] args)
    {
        Console.WriteLine("🚀 Reactive Channel Messaging System Starting...");
        Console.WriteLine("Choose mode: [1] Message Demo  [2] Communication Demo  [3] Both");
        
        var choice = Console.ReadKey(true).KeyChar;
        Console.WriteLine();
        
        switch (choice)
        {
            case '1':
                await RunMessageDemo(args);
                break;
            case '2':
                await CommunicationDemo.RunCommunicationDemo(args);
                break;
            case '3':
                Console.WriteLine("🎆 Running both demos...");
                var task1 = RunMessageDemo(args);
                var task2 = CommunicationDemo.RunCommunicationDemo(args);
                await Task.WhenAny(task1, task2);
                break;
            default:
                await RunMessageDemo(args);
                break;
        }
    }

    static async Task RunMessageDemo(string[] args)
    {

        // 配置依赖注入和日志
        var host = Host.CreateDefaultBuilder(args)
            .ConfigureServices((context, services) =>
            {
                services.AddSingleton<ReactiveMessageBus>();
                services.AddHostedService<MessageOrchestrator>();
                services.AddLogging(builder =>
                {
                    builder.AddConsole();
                    builder.SetMinimumLevel(LogLevel.Information);
                });
            })
            .Build();

        // 启动系统
        var hostTask = host.RunAsync();

        // 获取服务实例
        var messageBus = host.Services.GetRequiredService<ReactiveMessageBus>();
        var orchestrator = host.Services.GetRequiredService<IHostedService>() as MessageOrchestrator;

        // 设置控制台监控
        SetupConsoleMonitoring(messageBus, orchestrator!);

        // 运行演示场景
        var demoTask = RunDemoScenariosAsync(messageBus);

        Console.WriteLine("Press 'q' to quit, 'h' for help");
        await HandleUserInputAsync(messageBus);

        // 优雅关闭
        await host.StopAsync();
        await hostTask;
        await messageBus.DisposeAsync();
    }

    private static void SetupConsoleMonitoring(ReactiveMessageBus messageBus, MessageOrchestrator orchestrator)
    {
        // 监控编排事件
        orchestrator.OrchestrationEvents
            .Subscribe(eventMsg =>
            {
                Console.WriteLine($"📋 [ORCHESTRATION] {eventMsg}");
            });

        // 监控性能指标
        orchestrator.PerformanceMetrics
            .Sample(TimeSpan.FromSeconds(30))
            .Subscribe(metrics =>
            {
                Console.WriteLine($"📊 [PERFORMANCE] Total: {metrics.TotalMessages}, " +
                    $"Rate: {metrics.MessagesPerSecond:F1}/sec, Pending: {metrics.PendingCommands}");
            });

        // 监控健康状态
        messageBus.HealthStatus
            .DistinctUntilChanged()
            .Subscribe(isHealthy =>
            {
                var emoji = isHealthy ? "💚" : "❤️";
                Console.WriteLine($"{emoji} [HEALTH] System is {(isHealthy ? "healthy" : "unhealthy")}");
            });

        // 监控错误
        messageBus.Errors
            .Subscribe(error =>
            {
                Console.WriteLine($"❌ [ERROR] {error.GetType().Name}: {error.Message}");
            });
    }

    private static async Task RunDemoScenariosAsync(ReactiveMessageBus messageBus)
    {
        Console.WriteLine("🎬 Starting demo scenarios...");

        // 场景1: 批量数据处理
        _ = Task.Run(async () =>
        {
            await Task.Delay(2000); // 等待系统初始化
            
            for (int i = 0; i < 20; i++)
            {
                var dataMessage = new DataMessage(
                    Guid.NewGuid(),
                    DateTime.UtcNow,
                    $"DataSource{i % 3}",
                    $"Sample data item {i}",
                    Random.Shared.Next(1, 6)
                );

                await messageBus.PublishAsync(dataMessage);
                await Task.Delay(500);
            }
        });

        // 场景2: 事件流处理
        _ = Task.Run(async () =>
        {
            await Task.Delay(3000);
            
            var eventTypes = new[] { "UserLogin", "OrderCreated", "PaymentProcessed", "DataSync" };
            
            for (int i = 0; i < 15; i++)
            {
                var eventMessage = new EventMessage(
                    Guid.NewGuid(),
                    DateTime.UtcNow,
                    "EventSystem",
                    eventTypes[i % eventTypes.Length],
                    new { UserId = $"user{i}", SessionId = Guid.NewGuid() }
                );

                await messageBus.PublishAsync(eventMessage);
                await Task.Delay(800);
            }
        });

        // 场景3: 命令执行和响应
        _ = Task.Run(async () =>
        {
            await Task.Delay(4000);
            
            var commands = new[]
            {
                ("calculate", new Dictionary<string, object> { { "operation", "add" }, { "x", 10 }, { "y", 5 } }),
                ("fetch_data", new Dictionary<string, object> { { "id", "user123" } }),
                ("transform", new Dictionary<string, object> { { "input", "Hello World" } }),
                ("calculate", new Dictionary<string, object> { { "operation", "multiply" }, { "x", 7 }, { "y", 3 } })
            };

            foreach (var (command, parameters) in commands)
            {
                var commandMessage = new CommandMessage(
                    Guid.NewGuid(),
                    DateTime.UtcNow,
                    "CommandClient",
                    command,
                    parameters
                );

                await messageBus.PublishAsync(commandMessage);

                // 等待响应
                var response = await messageBus.SendCommand(commandMessage, TimeSpan.FromSeconds(5))
                    .FirstOrDefaultAsync();

                if (response != null)
                {
                    var status = response.Success ? "✅" : "❌";
                    Console.WriteLine($"{status} [COMMAND] {command} -> {(response.Success ? response.Result : response.Error)}");
                }

                await Task.Delay(1000);
            }
        });

        await Task.CompletedTask;
    }

    private static async Task HandleUserInputAsync(ReactiveMessageBus messageBus)
    {
        while (true)
        {
            var key = Console.ReadKey(true);
            
            switch (char.ToLower(key.KeyChar))
            {
                case 'q':
                    Console.WriteLine("🛑 Shutting down...");
                    return;
                
                case 'h':
                    PrintHelp();
                    break;
                
                case 'd':
                    await SendTestDataMessage(messageBus);
                    break;
                
                case 'e':
                    await SendTestEventMessage(messageBus);
                    break;
                
                case 'c':
                    await SendTestCommandMessage(messageBus);
                    break;
                
                case 's':
                    await ShowSystemStats(messageBus);
                    break;
                
                case 'f':
                    await FloodTest(messageBus);
                    break;
            }
        }
    }

    private static void PrintHelp()
    {
        Console.WriteLine("\n📖 Available Commands:");
        Console.WriteLine("  d - Send test data message");
        Console.WriteLine("  e - Send test event message");
        Console.WriteLine("  c - Send test command message");
        Console.WriteLine("  s - Show system statistics");
        Console.WriteLine("  f - Run flood test");
        Console.WriteLine("  h - Show this help");
        Console.WriteLine("  q - Quit application\n");
    }

    private static async Task SendTestDataMessage(ReactiveMessageBus messageBus)
    {
        var message = new DataMessage(
            Guid.NewGuid(),
            DateTime.UtcNow,
            "ManualInput",
            $"Manual test data {DateTime.Now:HH:mm:ss}",
            5
        );

        var success = await messageBus.PublishAsync(message);
        Console.WriteLine($"📤 Data message sent: {(success ? "✅" : "❌")}");
    }

    private static async Task SendTestEventMessage(ReactiveMessageBus messageBus)
    {
        var message = new EventMessage(
            Guid.NewGuid(),
            DateTime.UtcNow,
            "ManualInput",
            "TestEvent",
            new { TestData = "Manual event trigger", Timestamp = DateTime.UtcNow }
        );

        var success = await messageBus.PublishAsync(message);
        Console.WriteLine($"📤 Event message sent: {(success ? "✅" : "❌")}");
    }

    private static async Task SendTestCommandMessage(ReactiveMessageBus messageBus)
    {
        var message = new CommandMessage(
            Guid.NewGuid(),
            DateTime.UtcNow,
            "ManualInput",
            "calculate",
            new Dictionary<string, object> { { "operation", "add" }, { "x", 42 }, { "y", 8 } }
        );

        await messageBus.PublishAsync(message);
        
        var response = await messageBus.SendCommand(message, TimeSpan.FromSeconds(3))
            .FirstOrDefaultAsync();

        var result = response?.Success == true ? response.Result?.ToString() : "Failed";
        Console.WriteLine($"📤 Command sent, result: {result}");
    }

    private static async Task ShowSystemStats(ReactiveMessageBus messageBus)
    {
        Console.WriteLine("📊 Fetching system statistics...");
        
        var stats = await messageBus.GetMessageStats(TimeSpan.FromMinutes(5))
            .FirstOrDefaultAsync();

        if (stats != null)
        {
            Console.WriteLine($"📈 Statistics (last 5 minutes):");
            foreach (var kvp in stats.MessageCounts)
            {
                Console.WriteLine($"  {kvp.Key}: {kvp.Value} messages");
            }
        }
        else
        {
            Console.WriteLine("📈 No statistics available yet");
        }
    }

    private static async Task FloodTest(ReactiveMessageBus messageBus)
    {
        Console.WriteLine("🌊 Running flood test (100 messages)...");
        
        var tasks = new List<Task>();
        var stopwatch = System.Diagnostics.Stopwatch.StartNew();

        for (int i = 0; i < 100; i++)
        {
            var message = new DataMessage(
                Guid.NewGuid(),
                DateTime.UtcNow,
                "FloodTest",
                $"Flood message {i}",
                i % 5
            );

            tasks.Add(messageBus.PublishAsync(message).AsTask());
        }

        await Task.WhenAll(tasks);
        stopwatch.Stop();

        Console.WriteLine($"🌊 Flood test completed in {stopwatch.ElapsedMilliseconds}ms");
    }
}